#include "liveness.h"

// livenessmap = key : char * name ; value : 坐标;
HashMap *Livenessmap;
// element : livevalue
List *Liveness;

void initmap()
{
    Liveness = ListInit();
    Livenessmap = HashMapInit();
}


void buildliveness(pTAC node)
{
    //一般末尾都是endfunc
    for (pTAC cur = node->last->last; cur != node->last; cur = cur->last)
    {
        if (cur->type == TACType_Def)
        {
            if (cur->dest != NULL && cur->dest[0] != '#')
            {
                builddest(cur);
            }
            if (cur->left != NULL && cur->left[0] != '#')
            {
                buildleft(cur);
            }
            if (cur->right != NULL && cur->right[0] != '#')
            {
                buildright(cur);
            }
        }
        else if (cur->type == TACType_IfGo)
        {
            if (cur->left != NULL && cur->left[0] != '#')
            {
                buildleft(cur);
            }
            if (cur->right != NULL && cur->right[0] != '#')
            {
                buildright(cur);
            }
        }
        else if (cur->type == TACType_Return)
        {
            if (cur->dest != NULL && cur->dest[0] != '#')
            {
                builddest(cur);
            }
        }
        else if (cur->type == TACType_Param)
        {
            if (cur->dest != NULL)
            {
                builddest(cur);
            }
        }
    }
}

void builddest(pTAC node)
{
    //判断DEST
    int temhash = hash(node->dest);
    if (HashMapContain(Livenessmap, temhash))
    {
        ;
    }
    else
    {
        // HashMap 不包含
        plivevalue value = malloc(sizeof(livevalue));
        value->name = node->dest;
        value->startNODEID = node->node_ID;
        value->endNODEID = node->node_ID;
        ListPushBack(Liveness, value);
        int i = ListSize(Liveness) - 1;
        
        HashMapPut(Livenessmap, temhash, i);
    }
}

void buildleft(pTAC node)
{
    //判断LEFT
    int temhash = hash(node->left);
    if (HashMapContain(Livenessmap, temhash))
    {
        void *pget;
        pget = HashMapGet(Livenessmap, temhash);
        int get = pget;
        get = get;
        ListGetAt(Liveness, get, &pget);
        plivevalue getval = pget;
        plivevalue tem = malloc(sizeof(livevalue));
        tem->name = getval->name;
        tem->endNODEID = getval->endNODEID;
        tem->startNODEID = node->node_ID;
        free(getval);
        //bool i = ListInsert(Liveness, get, tem);
        ListSetAt(Liveness, get, tem);
        //printf("%d",i);
    }
    else
    {
        // HashMap 不包含
        plivevalue value = malloc(sizeof(livevalue));
        value->name = node->left;
        value->startNODEID = node->node_ID;
        value->endNODEID = node->node_ID;
        ListPushBack(Liveness, value);
        int i = ListSize(Liveness) - 1;
        HashMapPut(Livenessmap, temhash, i);
    }
}

void buildright(pTAC node)
{
    //判断LEFT
    int temhash = hash(node->right);
    if (HashMapContain(Livenessmap, temhash))
    {

        void *pget;
        pget = HashMapGet(Livenessmap, temhash);
        int get = pget;
        get = get;
        ListGetAt(Liveness, get, &pget);
        plivevalue getval = pget;
        plivevalue tem = malloc(sizeof(livevalue));
        tem->name = getval->name;
        tem->endNODEID = getval->endNODEID;
        tem->startNODEID = node->node_ID;
        free(getval);
        //ListInsert(Liveness, get, tem);
        ListSetAt(Liveness, get, tem);
        
    }
    else
    {
        // HashMap 不包含
        plivevalue value = malloc(sizeof(livevalue));
        value->name = node->right;
        value->startNODEID = node->node_ID;
        value->endNODEID = node->node_ID;
        ListPushBack(Liveness, value);
        int i = ListSize(Liveness) - 1;
        HashMapPut(Livenessmap, temhash, i);
    }
}

List *in;
List *out;

pTACHeadList newTACHEADnode()
{
    pTACHeadList node = malloc(sizeof(TACHeadList));
    if (node == NULL)
    {
        printf("run out of memory.\n");
        exit(0);
    }
    memset(node, 0, sizeof(TACHeadList));
    node->left = NULL;
    node->right = NULL;
    return node;
}

pTACHeadList blockTAC(pTACHeadList left, pTAC node)
{
    in = ListInit();
    out = ListInit();
    pTAC curnode = node->next;
    // ListPushBack(in, node->node_ID);
    for (; curnode != NULL; curnode = curnode->next)
    {
        if (curnode->type == TACType_Go)
        {
            ListPushBack(out, curnode->node_ID);
            ListPushBack(in, curnode->dest);
        }
        else if (curnode->type == TACType_IfGo)
        {
            ListPushBack(out, curnode->node_ID);
            ListPushBack(in, curnode->dest);
            ListPushBack(in, ++curnode->node_ID);
        }
    }
    pTACHeadList blockcur = newTACHEADnode();
    pTACHeadList returnblock = blockcur;
    curnode = node;
    blockcur->headnode = curnode;
    int *pinID, poutID;
    int inID, outID;
    ListGetFront(in, &pinID);
    ListGetFront(out, &outID);
    inID = pinID;
    outID = poutID;
    ListPopFront(in);
    ListPopFront(out);
    for (; curnode->next != NULL;)
    {
        if (inID == outID)
        {
            for (; curnode->node_ID != outID - 1 && curnode->next != NULL; curnode = curnode->next)
            {
                ;
            }
            pTACHeadList tem = newTACHEADnode();
            tem->left = blockcur;
            blockcur->right = tem;
            tem->headnode = curnode->next;
            curnode = curnode->next;
            blockcur = tem;
            ListGetFront(in, &pinID);
            ListGetFront(out, &outID);
            inID = pinID;
            outID = poutID;
            ListPopFront(in);
            ListPopFront(out);
        }
        else if (inID > outID)
        {
            for (; curnode->node_ID != outID - 1 && curnode->next != NULL; curnode = curnode->next)
            {
                ;
            }
            pTACHeadList tem = newTACHEADnode();
            tem->left = blockcur;
            blockcur->right = tem;
            tem->headnode = curnode->next;
            curnode = curnode->next;
            blockcur = tem;
            ListGetFront(out, &outID);
            outID = poutID;
            ListPopFront(out);
        }
        else
        {
            for (; curnode->node_ID != inID - 1 && curnode->next != NULL; curnode = curnode->next)
            {
                ;
            }
            pTACHeadList tem = newTACHEADnode();
            tem->left = blockcur;
            blockcur->right = tem;
            tem->headnode = curnode->next;
            curnode = curnode->next;
            blockcur = tem;
            ListGetFront(in, &inID);
            inID = pinID;
            ListPopFront(in);
        }
    }
    return returnblock;
}

void showallliveness()
{
    int listsize = ListSize(Liveness);
    for (size_t i = 0; i < listsize; i++)
    {
        void *pget;
        ListGetAt(Liveness, i, &pget);
        plivevalue node = pget;

        printf("%s :: start  %d ; end %d \n", node->name, node->startNODEID, node->endNODEID);
    }
}